﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Authorization.Roles;
using Abp.Authorization.Users;
using Abp.AutoMapper;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.Notifications;
using Abp.Runtime.Session;
using Abp.UI;
using Abp.Zero.Configuration;
using LeadThing.AbpZeroTemplate.Areas;
using LeadThing.AbpZeroTemplate.Authorization.Permissions;
using LeadThing.AbpZeroTemplate.Authorization.Permissions.Dto;
using LeadThing.AbpZeroTemplate.Authorization.Roles;
using LeadThing.AbpZeroTemplate.Authorization.Roles.Dto;
using LeadThing.AbpZeroTemplate.Authorization.Users.Dto;
using LeadThing.AbpZeroTemplate.Authorization.Users.Exporting;
using LeadThing.AbpZeroTemplate.BasicPersons.Authorization;
using LeadThing.AbpZeroTemplate.Configuration;
using LeadThing.AbpZeroTemplate.Dto;
using LeadThing.AbpZeroTemplate.Files;
using LeadThing.AbpZeroTemplate.Notifications;
using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Diagnostics;
using System.Linq;
using System.Linq.Dynamic;
using System.Threading.Tasks;
using System.Text;
using System.Data;

namespace LeadThing.AbpZeroTemplate.Authorization.Users
{
    //[AbpAuthorize(AppPermissions.Pages_Administration_Users)]
    //[AbpAuthorize(BasicPersonAppPermissions.GridPerson_Users)]

    public class UserAppService : AbpZeroTemplateAppServiceBase, IUserAppService
    {
        private readonly RoleManager _roleManager;
        private readonly IUserEmailer _userEmailer;
        private readonly IUserListExcelExporter _userListExcelExporter;
        private readonly INotificationSubscriptionManager _notificationSubscriptionManager;
        private readonly IAppNotifier _appNotifier;
        private readonly IRepository<RolePermissionSetting, long> _rolePermissionRepository;
        private readonly IRepository<UserPermissionSetting, long> _userPermissionRepository;
        private readonly IRepository<UserRole, long> _userRoleRepository;
        private readonly IUserPolicy _userPolicy;
        private readonly IRepository<User, long> _userRepository;
        private readonly IRepository<File, long> _fileRepository;
        private readonly IRoleAppService _roleService;//角色
        private readonly IRepository<Area, long> _areaRepository;
        private readonly ISqlExecuter _sqlExecuter;//sql语句接口

        public UserAppService(
            RoleManager roleManager,
            IUserEmailer userEmailer,
            IUserListExcelExporter userListExcelExporter,
            INotificationSubscriptionManager notificationSubscriptionManager,
            IAppNotifier appNotifier,
            IRepository<RolePermissionSetting, long> rolePermissionRepository,
            IRepository<UserPermissionSetting, long> userPermissionRepository,
            IRepository<UserRole, long> userRoleRepository,
            IUserPolicy userPolicy,
            IRepository<User, long> userRepository,
            IRepository<File, long> fileRepository,
            IRoleAppService roleService,
            IRepository<Area, long> areaRepository,
            ISqlExecuter sqlExecuter)
        {
            _roleManager = roleManager;
            _userEmailer = userEmailer;
            _userListExcelExporter = userListExcelExporter;
            _notificationSubscriptionManager = notificationSubscriptionManager;
            _appNotifier = appNotifier;
            _rolePermissionRepository = rolePermissionRepository;
            _userPermissionRepository = userPermissionRepository;
            _userRoleRepository = userRoleRepository;
            _userPolicy = userPolicy;
            _userRepository = userRepository;
            _fileRepository = fileRepository;
            _roleService = roleService;
            _areaRepository = areaRepository;
            _sqlExecuter = sqlExecuter;
        }

        #region 扩展方法

        private IQueryable<User> _userRepositoryAsNoTrack => _userRepository.GetAll().AsNoTracking();

        /// <summary>
        /// 获取所有用户信息加载到前台地图
        /// </summary>
        /// <returns></returns>
        public PagedResultDto<UsersLoadPageDto> GetAllUsersLoadPage(GetUsersInput input)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(@"select  TOP {0} [Id],[Name],[PhoneNumber],[UserType]
                         ,'TownTitle' = 
	                        CASE
                                WHEN [TownID] > 0 THEN (select top 1 Title from Basic.Area where Id = [TownID])
                                ELSE ''
                            END
                         ,'AreaTitle' = 
	                        CASE
                                WHEN [TownID] > 0 THEN (select top 1 Title from Basic.Area where Id = [AreaID])
                                ELSE ''
                            END
                         ,'VillageTitle' = 
	                        CASE
                                WHEN [TownID] > 0 THEN (select top 1 Title from Basic.Area where Id = [VillageID])
                                ELSE ''
                            END
                         ,'XPoint' =
                            CASE
                                WHEN [VillageID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [VillageID])
                                WHEN [AreaID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [AreaID])
                                WHEN [TownID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [TownID])
                                ELSE ''
                            END
                          ,'YPoint' =
                            CASE
                                WHEN [VillageID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [VillageID])
                                WHEN [AreaID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [AreaID])
                                WHEN [TownID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [TownID])
                                ELSE ''
                            END
                         from AbpUsers where Name <> 'admin' and isDeleted=0 ", input.MaxResultCount);

            var query = _userRepositoryAsNoTrack;
            query = query.Where(u => u.Name != "admin");
            string skip = " and Id not in(select top " + input.SkipCount + " Id from AbpUsers where Name <> 'admin' and isDeleted=0 {0})";
            string skip1 = "";
            if (!string.IsNullOrWhiteSpace(input.UserType))
            {
                sb.Append(" and UserType='");
                sb.Append(input.UserType);
                sb.Append("' ");
                skip1 += string.Format(" and UserType= '{0}'", input.UserType);
                query = query.Where(u => u.UserType == input.UserType);
            }

            if (!string.IsNullOrWhiteSpace(input.Filter))
            {
                sb.Append(" and Name like '%");
                sb.Append(input.Filter);
                sb.Append("%' ");
                skip1 += string.Format(" and Name like '%{0}%'", input.Filter);
                query = query.Where(u => u.Name.Contains(input.Filter));
            }
            var count = query.Count();
            if (skip1 != "")
            {
                skip = string.Format(skip, skip1);
            }
            var list = _sqlExecuter.SqlQuery<UsersLoadPageDto>(sb.ToString() + skip).ToList();

            return new PagedResultDto<UsersLoadPageDto>(count, list);
        }

        /// <summary>
        /// 根据条件和角色获取所有用户数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ListResultDto<UserListDto>> GetAllUsersByWhereAndRole(GetUsersInput input)
        {
            var query = UserManager.Users;

            #region 权限验证

            var userID = AbpSession.GetUserId();
            var userModel = _userRepository.FirstOrDefault(userID);
            GetRolesInput input_role = new GetRolesInput() { UserId = userID };
            var role = await _roleService.GetRolesByUserId(input_role);

            if (role.DisplayName == "乡镇网格管理员")
                query = query.Where(p => p.TownID == userModel.TownID || p.CreatorUserId == userID);
            else if (role.DisplayName == "社区网格管理员")
                query = query.Where(p => p.AreaID == userModel.AreaID || p.CreatorUserId == userID);
            else if (role.DisplayName == "村庄网格管理员")
                query = query.Where(p => p.VillageID == userModel.VillageID || p.CreatorUserId == userID);

            #endregion 权限验证

            query = query.Where(p => p.Id != 1 && p.Id != 2);

            var items = await query.ToListAsync();

            return new ListResultDto<UserListDto>(
                items.Select(item =>
                {
                    var dto = item.MapTo<UserListDto>();
                    return dto;
                }).ToList());
        }

        /// <summary>
        /// 根据条件获取所有用户数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ListResultDto<UserListDto>> GetAllUsersByWhere(GetUsersInput input)
        {
            var query = UserManager.Users;
            query = query.Where(p => p.Id != 1 && p.Id != 2);
            var items = await query.ToListAsync();

            return new ListResultDto<UserListDto>(
                items.Select(item =>
                {
                    var dto = item.MapTo<UserListDto>();
                    return dto;
                }).ToList());
        }

        /// <summary>
        /// 根据UserId获取用户数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<UserEditDto> GetUsersGyUserId(GetUsersInput input)
        {
            var query = from user in UserManager.Users
                        where user.Id == input.UserId
                        select user;
            var model = await query.FirstOrDefaultAsync();
            return model.MapTo<UserEditDto>();
        }

        #endregion 扩展方法

        #region 用户管理

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_Users, BasicPersonAppPermissions.RegisterPerson_Users)]
        public async Task<PagedResultDto<UserListDto>> GetUsers(GetUsersInput input)
        {
            var query = UserManager.Users
                .Include(u => u.Roles)
                .WhereIf(input.Role.HasValue, u => u.Roles.Any(r => r.RoleId == input.Role.Value))
                .WhereIf(
                    !input.Filter.IsNullOrWhiteSpace(),
                    u =>
                        u.Name.Contains(input.Filter) ||
                        u.Surname.Contains(input.Filter) ||
                        u.UserName.Contains(input.Filter) ||
                        u.EmailAddress.Contains(input.Filter)
                )
                .WhereIf(!input.PhoneNumber.IsNullOrWhiteSpace(), u => u.PhoneNumber.Contains(input.PhoneNumber));

            if (!string.IsNullOrEmpty(input.UserType))
            {
                query = query.Where(p => p.UserType == input.UserType);
            }
            //镇
            if (input.TownID > 0)
                query = query.Where(p => p.TownID == input.TownID);

            //区
            if (input.AreaID > 0)
                query = query.Where(p => p.AreaID == input.AreaID);

            //村庄
            if (input.VillageID > 0)
                query = query.Where(p => p.VillageID == input.VillageID);

            if (!input.Permission.IsNullOrWhiteSpace())
            {
                query = (from user in query
                         join ur in _userRoleRepository.GetAll() on user.Id equals ur.UserId into urJoined
                         from ur in urJoined.DefaultIfEmpty()
                         join up in _userPermissionRepository.GetAll() on new { UserId = user.Id, Name = input.Permission } equals new { up.UserId, up.Name } into upJoined
                         from up in upJoined.DefaultIfEmpty()
                         join rp in _rolePermissionRepository.GetAll() on new { RoleId = ur.RoleId, Name = input.Permission } equals new { rp.RoleId, rp.Name } into rpJoined
                         from rp in rpJoined.DefaultIfEmpty()
                         where (up != null && up.IsGranted) || (up == null && rp != null)
                         group user by user into userGrouped
                         select userGrouped.Key);
            }

            var userCount = await query.CountAsync();
            var users = await query
                .OrderByDescending(p => p.SortID)
                .OrderByDescending(p => p.Id)
                .PageBy(input)
                .ToListAsync();

            var areaList = _areaRepository.GetAll();
            var userListDtos = users.MapTo<List<UserListDto>>();
            await FillRoleNames(userListDtos);

            return new PagedResultDto<UserListDto>(
                userCount,
                userListDtos.Select(item =>
                {
                    var dto = item;
                    var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                    if (townModel != null)
                        dto.TownTitle = townModel.Title;

                    var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                    if (areaModel != null)
                        dto.AreaTitle = areaModel.Title;

                    var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                    if (villModel != null)
                        dto.VillageTitle = villModel.Title;

                    return dto;
                }).ToList());
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_Users, BasicPersonAppPermissions.RegisterPerson_Users)]
        public async Task<PagedResultDto<UserCountListDto>> GetUserCountByGroup(GetUsersInput input)
        {
            var scerachId = 0;
            var type = "TownID";
            //镇
            if (input.TownID > 0) scerachId = input.TownID;
            //区
            if (input.AreaID > 0)
            {
                scerachId = input.AreaID;
                type = "AreaID";
            }
            //村庄
            if (input.VillageID > 0)
            {
                scerachId = input.VillageID;
                type = "VillageID";
            }

            var areaQuery = _areaRepository.GetAll();
            var areaList = areaQuery.Where(a => a.ParentId == scerachId).ToList();
            if (areaList.Count == 0)
                areaList = areaQuery.Where(a => a.Id == scerachId).ToList();

            var areaIds = areaList.Select(a => a.Id).ToList();

            var resultList = new List<UserCountListDto>(areaIds.Count);
            foreach (var area in areaList)
            {
                UserCountListDto res = new UserCountListDto { Id = area.Id, Name = area.Title };
                if (scerachId > 0)
                {
                    if (type == "TownID")
                        res.UserCount = await UserManager.Users.CountAsync(u => u.TownID == input.TownID && u.AreaID == area.Id && u.UserType == input.UserType);
                    else if (type == "AreaID" || type == "VillageID")
                        res.UserCount = await UserManager.Users.CountAsync(u => u.TownID == input.TownID && u.AreaID == input.AreaID && u.VillageID == area.Id && u.UserType == input.UserType);
                }
                else
                    res.UserCount = await UserManager.Users.CountAsync(u => u.TownID == area.Id && u.UserType == input.UserType);

                resultList.Add(res);
            }

            return new PagedResultDto<UserCountListDto>(areaIds.Count, resultList); ;
        }



        /// <summary>
        /// 获取当前用户信息
        /// </summary>
        /// <returns></returns>
        public async Task<UserListDto> GetCurrentUserDto()
        {
            //查看注册群众时，最后要根据自身的镇区村来进行过滤
            User currUser = base.GetCurrentUser();
            var currUserDto = currUser.MapTo<UserListDto>();
            var role = await _roleService.GetRolesByUserId(new GetRolesInput { UserId = currUserDto.Id });
            currUserDto.RoleName = role.DisplayName;

            return currUserDto;
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_Users, BasicPersonAppPermissions.RegisterPerson_Users)]
        public async Task<FileDto> GetUsersToExcel()
        {
            var users = await UserManager.Users.Include(u => u.Roles).ToListAsync();
            var userListDtos = users.MapTo<List<UserListDto>>();
            await FillRoleNames(userListDtos);

            return _userListExcelExporter.ExportToFile(userListDtos);
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_Users, BasicPersonAppPermissions.RegisterPerson_Users)]
        public async Task<FileDto> GetUsersByFilterToExcel(GetUsersInput input)
        {
            var query = UserManager.Users
            .Include(u => u.Roles)
            .WhereIf(input.Role.HasValue, u => u.Roles.Any(r => r.RoleId == input.Role.Value))
            .WhereIf(
                !input.Filter.IsNullOrWhiteSpace(),
                    u =>
                    u.Name.Contains(input.Filter) ||
                    u.Surname.Contains(input.Filter) ||
                    u.UserName.Contains(input.Filter) ||
                    u.EmailAddress.Contains(input.Filter)
            )
            .WhereIf(!input.PhoneNumber.IsNullOrWhiteSpace(), u => u.PhoneNumber.Contains(input.PhoneNumber));

            if (!string.IsNullOrEmpty(input.UserType))
            {
                query = query.Where(p => p.UserType == input.UserType);
            }
            //镇
            if (input.TownID > 0)
                query = query.Where(p => p.TownID == input.TownID);

            //区
            if (input.AreaID > 0)
                query = query.Where(p => p.AreaID == input.AreaID);

            //村庄
            if (input.VillageID > 0)
                query = query.Where(p => p.VillageID == input.VillageID);

            if (!input.Permission.IsNullOrWhiteSpace())
            {
                query = (from user in query
                         join ur in _userRoleRepository.GetAll() on user.Id equals ur.UserId into urJoined
                         from ur in urJoined.DefaultIfEmpty()
                         join up in _userPermissionRepository.GetAll() on new { UserId = user.Id, Name = input.Permission } equals new { up.UserId, up.Name } into upJoined
                         from up in upJoined.DefaultIfEmpty()
                         join rp in _rolePermissionRepository.GetAll() on new { RoleId = ur.RoleId, Name = input.Permission } equals new { rp.RoleId, rp.Name } into rpJoined
                         from rp in rpJoined.DefaultIfEmpty()
                         where (up != null && up.IsGranted) || (up == null && rp != null)
                         group user by user into userGrouped
                         select userGrouped.Key);
            }

            var users = await query
                .OrderByDescending(p => p.SortID)
                .OrderByDescending(p => p.Id)
                .ToListAsync();
            var userListDtos = users.MapTo<List<UserListDto>>();

            var areaList = _areaRepository.GetAll();
            userListDtos.ForEach(dto => {
                var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                if (townModel != null)
                    dto.TownTitle = townModel.Title;

                var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                if (areaModel != null)
                    dto.AreaTitle = areaModel.Title;

                var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                if (villModel != null)
                    dto.VillageTitle = villModel.Title;
            });

            return _userListExcelExporter.ExportToFile(userListDtos);
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_Users, BasicPersonAppPermissions.RegisterPerson_Users)]
        public async Task<FileDto> DownloadUsersTemplateExcel()
        {
            return _userListExcelExporter.DownloadUsersTemplateExcel();
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_CreatingNewUser, BasicPersonAppPermissions.GridPerson_EditingUser, BasicPersonAppPermissions.RegisterPerson_CreatingNewUser, BasicPersonAppPermissions.RegisterPerson_EditingUser)]
        public async Task<GetUserForEditOutput> GetUserForEdit(NullableIdDto<long> input)
        {
            //Getting all available roles
            var userRoleDtos = (await _roleManager.Roles
                .OrderBy(r => r.DisplayName)
                .Select(r => new UserRoleDto
                {
                    RoleId = r.Id,
                    RoleName = r.Name,
                    RoleDisplayName = r.DisplayName
                })
                .ToArrayAsync());

            var output = new GetUserForEditOutput
            {
                Roles = userRoleDtos
            };

            if (!input.Id.HasValue)
            {
                //Creating a new user
                output.User = new UserEditDto
                {
                    IsActive = true,
                    ShouldChangePasswordOnNextLogin = true,
                    IsTwoFactorEnabled = await SettingManager.GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsEnabled),
                    IsLockoutEnabled = await SettingManager.GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.UserLockOut.IsEnabled)
                };

                foreach (var defaultRole in await _roleManager.Roles.Where(r => r.IsDefault).ToListAsync())
                {
                    var defaultUserRole = userRoleDtos.FirstOrDefault(ur => ur.RoleName == defaultRole.Name);
                    if (defaultUserRole != null)
                    {
                        defaultUserRole.IsAssigned = true;
                    }
                }
            }
            else
            {
                //Editing an existing user
                var user = await UserManager.GetUserByIdAsync(input.Id.Value);

                output.User = user.MapTo<UserEditDto>();
                output.ProfilePictureId = user.ProfilePictureId;

                foreach (var userRoleDto in userRoleDtos)
                {
                    userRoleDto.IsAssigned = await UserManager.IsInRoleAsync(input.Id.Value, userRoleDto.RoleName);
                }
            }

            return output;
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_ChangingPermissions, BasicPersonAppPermissions.RegisterPerson_ChangingPermissions)]
        public async Task<GetUserPermissionsForEditOutput> GetUserPermissionsForEdit(EntityDto<long> input)
        {
            var user = await UserManager.GetUserByIdAsync(input.Id);
            var permissions = PermissionManager.GetAllPermissions();
            var grantedPermissions = await UserManager.GetGrantedPermissionsAsync(user);

            return new GetUserPermissionsForEditOutput
            {
                Permissions = permissions.MapTo<List<FlatPermissionDto>>().OrderBy(p => p.DisplayName).ToList(),
                GrantedPermissionNames = grantedPermissions.Select(p => p.Name).ToList()
            };
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_ChangingPermissions, BasicPersonAppPermissions.RegisterPerson_ChangingPermissions)]
        public async Task ResetUserSpecificPermissions(EntityDto<long> input)
        {
            var user = await UserManager.GetUserByIdAsync(input.Id);
            await UserManager.ResetAllPermissionsAsync(user);
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_ChangingPermissions, BasicPersonAppPermissions.RegisterPerson_ChangingPermissions)]
        public async Task UpdateUserPermissions(UpdateUserPermissionsInput input)
        {
            var user = await UserManager.GetUserByIdAsync(input.Id);
            var grantedPermissions = PermissionManager.GetPermissionsFromNamesByValidating(input.GrantedPermissionNames);
            await UserManager.SetGrantedPermissionsAsync(user, grantedPermissions);
        }

        public async Task CreateOrUpdateUser(CreateOrUpdateUserInput input)
        {
            if (input.User.Id.HasValue)
            {
                await UpdateUserAsync(input);
            }
            else
            {
                await CreateUserAsync(input);
            }
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_ChangingPermissions, BasicPersonAppPermissions.RegisterPerson_ChangingPermissions)]
        public async Task<ImportUsersResultDto> CreateUsersAsync(ImportUsersInputDto input)
        {
            CreateOrUpdateUserInput inputc = null;
            ImportUsersResultDto result = new ImportUsersResultDto();

            foreach (DataRow row in input.Users.Rows)
            {
                string name = row["姓名"].ToString();
                string userName = row["用户名"].ToString();
                string phoneNumber = row["电话号码"].ToString();
                if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(userName))
                {
                    continue;
                }

                inputc = new CreateOrUpdateUserInput
                {
                    User = new UserEditDto
                    {
                        Name = name,
                        Surname = "默认姓氏",
                        UserName = userName, //Same username is added before (in CreateTestUsers)
                        PhoneNumber = phoneNumber,
                        Password = "123456",
                        IsActive = true,
                        IsLockoutEnabled = true,
                        EmailAddress = Guid.NewGuid().ToString() + "@126.com",
                        UserType = "非群众"
                    },
                    AssignedRoleNames = new string[] { "2f59f68c3ea147b99b9da0b8e00aa676" }
                    //AssignedRoleNames = new string[0]
                };

                var userCount = _userRepository.GetAll().Where(p => p.UserName == userName).Count();
                if (userCount == 0)
                {
                    await CreateUserAsync(inputc);

                    result.SuccessUsers.Add(inputc.User);
                }
                else
                {
                    result.ErrorUsers.Add(inputc.User);
                }
            }

            return result;
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_DeletingUser, BasicPersonAppPermissions.RegisterPerson_DeletingUser)]
        public async Task DeleteUser(EntityDto<long> input)
        {
            if (input.Id == AbpSession.GetUserId())
            {
                throw new UserFriendlyException(L("YouCanNotDeleteOwnAccount"));
            }

            var user = await UserManager.GetUserByIdAsync(input.Id);
            CheckErrors(await UserManager.DeleteAsync(user));
        }

        public async Task UnlockUser(EntityDto<long> input)
        {
            var user = await UserManager.GetUserByIdAsync(input.Id);
            user.Unlock();
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_EditingUser, BasicPersonAppPermissions.RegisterPerson_EditingUser)]
        protected virtual async Task UpdateUserAsync(CreateOrUpdateUserInput input)
        {
            Debug.Assert(input.User.Id != null, "input.User.Id should be set.");

            var user = await UserManager.FindByIdAsync(input.User.Id.Value);

            //Update user properties
            input.User.MapTo(user); //Passwords is not mapped (see mapping configuration)

            if (input.SetRandomPassword)
            {
                input.User.Password = User.CreateRandomPassword();
            }

            if (!input.User.Password.IsNullOrEmpty())
            {
                CheckErrors(await UserManager.ChangePasswordAsync(user, input.User.Password));
            }

            CheckErrors(await UserManager.UpdateAsync(user));

            //Update roles
            CheckErrors(await UserManager.SetRoles(user, input.AssignedRoleNames));

            //if (input.SendActivationEmail)
            //{
            //    user.SetNewEmailConfirmationCode();
            //    await _userEmailer.SendEmailActivationLinkAsync(user, input.User.Password);
            //}
        }

        [AbpAuthorize(BasicPersonAppPermissions.GridPerson_CreatingNewUser, BasicPersonAppPermissions.RegisterPerson_CreatingNewUser)]
        protected virtual async Task CreateUserAsync(CreateOrUpdateUserInput input)
        {
            if (AbpSession.TenantId.HasValue)
            {
                await _userPolicy.CheckMaxUserCountAsync(AbpSession.GetTenantId());
            }

            var user = input.User.MapTo<User>(); //Passwords is not mapped (see mapping configuration)
            user.TenantId = AbpSession.TenantId;

            //Set password
            if (!input.User.Password.IsNullOrEmpty())
            {
                CheckErrors(await UserManager.PasswordValidator.ValidateAsync(input.User.Password));
            }
            else
            {
                input.User.Password = User.CreateRandomPassword();
            }

            user.Password = new PasswordHasher().HashPassword(input.User.Password);
            user.ShouldChangePasswordOnNextLogin = input.User.ShouldChangePasswordOnNextLogin;

            //Assign roles
            user.Roles = new Collection<UserRole>();
            foreach (var roleName in input.AssignedRoleNames)
            {
                var role = await _roleManager.GetRoleByNameAsync(roleName);
                user.Roles.Add(new UserRole(AbpSession.TenantId, user.Id, role.Id));
            }

            CheckErrors(await UserManager.CreateAsync(user));
            await CurrentUnitOfWork.SaveChangesAsync(); //To get new user's Id.

            //Notifications
            await _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync(user.ToUserIdentifier());
            await _appNotifier.WelcomeToTheApplicationAsync(user);

            //Send activation email
            //if (input.SendActivationEmail)
            //{
            //    user.SetNewEmailConfirmationCode();
            //    await _userEmailer.SendEmailActivationLinkAsync(user, input.User.Password);
            //}
        }

        private async Task FillRoleNames(List<UserListDto> userListDtos)
        {
            /* This method is optimized to fill role names to given list. */

            var distinctRoleIds = (
                from userListDto in userListDtos
                from userListRoleDto in userListDto.Roles
                select userListRoleDto.RoleId
                ).Distinct();

            var roleNames = new Dictionary<int, string>();
            foreach (var roleId in distinctRoleIds)
            {
                roleNames[roleId] = (await _roleManager.GetRoleByIdAsync(roleId)).DisplayName;
            }

            foreach (var userListDto in userListDtos)
            {
                foreach (var userListRoleDto in userListDto.Roles)
                {
                    userListRoleDto.RoleName = roleNames[userListRoleDto.RoleId];
                }

                userListDto.Roles = userListDto.Roles.OrderBy(r => r.RoleName).ToList();
            }
        }

        #endregion 用户管理

        #region APP接口

        /// <summary>
        /// 根据查询条件获取用户分页列表
        /// </summary>
        public async Task<PagedResultDto<UserListDto>> GetPagedUsersAppAsync(GetUsersAPPInput input)
        {
            var _pageIndex = Convert.ToInt32(input.PageIndex);
            var _pageSize = Convert.ToInt32(input.PageSize);
            var query = _userRepositoryAsNoTrack;

            #region TODO:根据传入的参数添加过滤条件

            //TODO:根据传入的参数添加过滤条件

            if (!string.IsNullOrWhiteSpace(input.Name))
            {
                query = query.Where(p => p.Name.Contains(input.Name));
            }

            #region 权限验证

            var userID = Convert.ToInt32(input.UserId);
            var userModel = _userRepository.FirstOrDefault(userID);
            GetRolesInput input_role = new GetRolesInput() { UserId = userID };
            var role = await _roleService.GetRolesByUserId(input_role);

            if (role.DisplayName == "县网格管理员")
                query = query.Where(p => p.AreaID == 0 && p.VillageID == 0);
            if (role.DisplayName == "乡镇网格管理员")
                query = query.Where(p => p.TownID == userModel.TownID && p.VillageID == 0);
            else if (role.DisplayName == "社区网格管理员")
                query = query.Where(p => p.AreaID == userModel.AreaID);
            else if (role.DisplayName == "村庄网格管理员")
                query = query.Where(p => p.VillageID == userModel.VillageID);

            query = query.Where(p => p.CreatorUserId != userID && p.UserType != "群众");

            #endregion 权限验证

            #endregion TODO:根据传入的参数添加过滤条件

            var userCount = await query.CountAsync();

            var users = await query
                .OrderByDescending(p => p.SortID)
            .OrderByDescending(p => p.Id)
            .Take(_pageSize * _pageIndex).Skip(_pageSize * (_pageIndex - 1))
            .ToListAsync();

            var fileList = _fileRepository.GetAll();
            var areaList = _areaRepository.GetAll();

            return new PagedResultDto<UserListDto>(userCount,
                users.Select(item =>
                {
                    var dto = item.MapTo<UserListDto>();

                    var fileModel = fileList.Where(p => p.Id == dto.FileID).FirstOrDefault();
                    if (fileModel != null)
                        dto.ImageUrl = AppSettings.AppSetting.AppUrl + fileModel.Url;
                    else
                        dto.ImageUrl = AppSettings.AppSetting.AppUrl + "/Common/Images/default-profile-picture.png";

                    var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                    if (townModel != null)
                        dto.TownTitle = townModel.Title;

                    var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                    if (areaModel != null)
                        dto.AreaTitle = areaModel.Title;

                    var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                    if (villModel != null)
                        dto.VillageTitle = villModel.Title;

                    return dto;
                }).ToList());
        }

        /// <summary>
        /// 根据UserId获取用户数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<UserEditDto> GetUsersGyUserIdAPP(GetUsersAPPInput input)
        {
            var userId = Convert.ToInt32(input.UserId);
            var query = from user in UserManager.Users
                        where user.Id == userId
                        select user;
            var model = await query.FirstOrDefaultAsync();

            var resultModel = model.MapTo<UserEditDto>();

            var fileModel = _fileRepository.GetAll().Where(p => p.Id == resultModel.FileID).FirstOrDefault();
            if (fileModel != null)
                resultModel.ImageUrl = AppSettings.AppSetting.AppUrl + fileModel.Url;
            else
                resultModel.ImageUrl = AppSettings.AppSetting.AppUrl + "/Common/Images/default-profile-picture.png";

            return resultModel;
        }

        /// <summary>
        /// 编辑用户数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public virtual async Task UpdateUserAPPAsync(UserEditAPPDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新
            var id = Convert.ToInt32(input.Id);
            var entity = await _userRepository.GetAsync(id);
            input.MapTo(entity);

            await _userRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 用户注册（群众）
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<RegisterDto> CreateUserAPPAsync(UserRegisterAPPDto input)
        {
            RegisterDto result = new RegisterDto();
            var user = new User()
            {
                Id = 0,
                TenantId = 1,
                Name = input.Name,
                Surname = "默认姓氏",
                UserName = input.PhoneNumber,
                Password = new PasswordHasher().HashPassword(input.Password),
                EmailAddress = Guid.NewGuid().ToString() + "@126.com",
                IsEmailConfirmed = false,
                PhoneNumber = input.PhoneNumber,
                IsActive = true,
                ShouldChangePasswordOnNextLogin = false,
                AccessFailedCount = 0,
                IsLockoutEnabled = true,
                IsPhoneNumberConfirmed = false,
                IsTwoFactorEnabled = false,
                TownID = Convert.ToInt32(input.TownID),
                AreaID = Convert.ToInt32(input.AreaID),
                VillageID = Convert.ToInt32(input.VillageID),
                UserType = "群众"
            };

            //验证
            var userCount = _userRepository.GetAll().Where(p => p.PhoneNumber == input.PhoneNumber).Count();
            if (userCount > 0)
            {
                result.Success = false;
                result.Message = "您的手机号已被注册";
                return result;
            }

            var roleModel = _roleManager.Roles.Where(p => p.DisplayName == "村庄网格管理员").FirstOrDefault();

            if (roleModel == null)
            {
                result.Success = false;
                result.Message = "暂无村庄网格管理员角色！";
                return result;
            }

            var userId = await _userRepository.InsertAndGetIdAsync(user);
            var roleResult = await UserManager.AddToRoleAsync(userId, roleModel.Name);

            if (userId > 0 && roleResult.Succeeded)
            {
                result.Success = true;
            }
            else
            {
                result.Success = false;
                result.Message = "注册失败";
            }

            //Notifications
            //await _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync(user.ToUserIdentifier());
            //await _appNotifier.WelcomeToTheApplicationAsync(user);

            //添加环信用户
            //HXComm.EaseMobDemo easeMob = new HXComm.EaseMobDemo();
            //easeMob.AccountCreate(user.Id.ToString(), "123456");

            return result;
        }


        /// <summary>
        /// 获取县管理员通讯录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        List<UserListDto> IUserAppService.GetCountyAdministratorMailList(GetUsersAPPInput input)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(@" select users.*,roles.DisplayName as RoleName,
                        (case
                          when files.url is null then 'http://61.162.225.227:887/Common/Images/default-profile-picture.png'
                          else 'http://61.162.225.227:887' + files.url end) as 'ImageUrl',
                        (select Title from Basic.Area where Id = users.TownID) as 'TownTitle',
                        (select Title from Basic.Area where Id = users.AreaID) as 'AreaTitle',
                        (select Title from Basic.Area where Id = users.VillageID) as 'VillageTitle' 
                        from AbpUsers users
                        left join [Basic].[File] files
                        on users.FileID = files.Id
                        left join AbpUserRoles urole
                        on urole.UserId = users.Id
                        left join AbpRoles roles
                        on urole.RoleId = roles.Id where users.UserType='非群众' ");

            if (input.RoleName == "县网格管理员" || input.RoleName == "乡镇网格管理员")
            {
                sb.Append(" and roles.DisplayName='县网格管理员' ");
            }
            else if (input.RoleName == "社区网格管理员")
            {
                sb.Append(string.Format(" and users.TownID={0} and roles.DisplayName='县网格管理员' ", input.TownID));
            }

            sb.Append(" order by users.SortID desc ");

            return _sqlExecuter.SqlQuery<UserListDto>(sb.ToString()).ToList();
        }

        /// <summary>
        /// 获取乡镇管理员通讯录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        List<UserListDto> IUserAppService.GetTownAdministratorMailList(GetUsersAPPInput input)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(@" select users.*,roles.DisplayName as RoleName,
                        (case
                          when files.url is null then 'http://61.162.225.227:887/Common/Images/default-profile-picture.png'
                          else 'http://61.162.225.227:887' + files.url end) as 'ImageUrl',
                        (select Title from Basic.Area where Id = users.TownID) as 'TownTitle',
                        (select Title from Basic.Area where Id = users.AreaID) as 'AreaTitle',
                        (select Title from Basic.Area where Id = users.VillageID) as 'VillageTitle' 
                        from AbpUsers users
                        left join [Basic].[File] files
                        on users.FileID = files.Id
                        left join AbpUserRoles urole
                        on urole.UserId = users.Id
                        left join AbpRoles roles
                        on urole.RoleId = roles.Id where users.UserType='非群众' ");

            if (input.RoleName == "县网格管理员")
            {
                sb.Append(" and roles.DisplayName='乡镇网格管理员' ");
            }
            else if (input.RoleName == "乡镇网格管理员" || input.RoleName == "社区网格管理员")
            {
                sb.Append(string.Format(" and users.TownID={0} and roles.DisplayName='乡镇网格管理员' ", input.TownID));
            }
            sb.Append(" order by users.SortID desc ");

            return _sqlExecuter.SqlQuery<UserListDto>(sb.ToString()).ToList();
        }

        /// <summary>
        /// 获取社区管理员通讯录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        List<UserListDto> IUserAppService.GetAreaAdministratorMailList(GetUsersAPPInput input)
        {
            StringBuilder sb = new StringBuilder();
            List<UserListDto> list = new List<UserListDto>();
            sb.Append(@" select users.*,roles.DisplayName as RoleName,
                        (case
                          when files.url is null then 'http://61.162.225.227:887/Common/Images/default-profile-picture.png'
                          else 'http://61.162.225.227:887' + files.url end) as 'ImageUrl',
                        (select Title from Basic.Area where Id = users.TownID) as 'TownTitle',
                        (select Title from Basic.Area where Id = users.AreaID) as 'AreaTitle',
                        (select Title from Basic.Area where Id = users.VillageID) as 'VillageTitle' 
                        from AbpUsers users
                        left join [Basic].[File] files
                        on users.FileID = files.Id
                        left join AbpUserRoles urole
                        on urole.UserId = users.Id
                        left join AbpRoles roles
                        on urole.RoleId = roles.Id where users.UserType='非群众' ");

            if (input.RoleName == "县网格管理员")
            {
                return list;
            }
            else if (input.RoleName == "乡镇网格管理员")
            {
                sb.Append(string.Format(" and users.TownID={0} and roles.DisplayName='社区网格管理员' ", input.TownID));
            }
            else if (input.RoleName == "社区网格管理员")
            {
                sb.Append(string.Format(" and users.TownID={0} and users.AreaID={1} and roles.DisplayName='社区网格管理员' ", input.TownID, input.AreaID));
            }
            sb.Append(" order by users.SortID desc ");

            return _sqlExecuter.SqlQuery<UserListDto>(sb.ToString()).ToList();
        }


        /// <summary>
        /// 获取村庄管理员通讯录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        List<UserListDto> IUserAppService.GetVillageAdministratorMailList(GetUsersAPPInput input)
        {
            StringBuilder sb = new StringBuilder();
            List<UserListDto> list = new List<UserListDto>();
            sb.Append(@" select users.*,roles.DisplayName as RoleName,
                        (case
                          when files.url is null then 'http://61.162.225.227:887/Common/Images/default-profile-picture.png'
                          else 'http://61.162.225.227:887' + files.url end) as 'ImageUrl',
                        (select Title from Basic.Area where Id = users.TownID) as 'TownTitle',
                        (select Title from Basic.Area where Id = users.AreaID) as 'AreaTitle',
                        (select Title from Basic.Area where Id = users.VillageID) as 'VillageTitle' 
                        from AbpUsers users
                        left join [Basic].[File] files
                        on users.FileID = files.Id
                        left join AbpUserRoles urole
                        on urole.UserId = users.Id
                        left join AbpRoles roles
                        on urole.RoleId = roles.Id where users.UserType='非群众' ");

            if (input.RoleName == "县网格管理员" || input.RoleName == "乡镇网格管理员")
            {
                return list;
            }
            else if (input.RoleName == "社区网格管理员")
            {
                sb.Append(string.Format(" and users.TownID={0} and users.AreaID={1} and roles.DisplayName='村庄网格管理员' ", input.TownID, input.AreaID));
            }
            sb.Append(" order by users.SortID desc ");

            return _sqlExecuter.SqlQuery<UserListDto>(sb.ToString()).ToList();
        }

        #endregion APP接口
    }
}